package com.kcht.test.rfid;

import lombok.extern.slf4j.Slf4j;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import java.util.ArrayList;
import java.util.List;

@Slf4j
@Component
public class EventExecutor {
    //每次事件生成关键字
    private String key;
    @Value("${service.uri:}")
    private String uri;

    /**
     * 每60s尝试一次新事件
     * */
    private int  period=60000;
    /**
     * 控制事件从触发到形成报告时间为(24~30s)
     */
    private int duration = 24000;

    /**
     * 服务走完整个流程需要的时间
     */
    private int serviceFinishTime = 12000;
    /**
     * 触发开始事件的时间占用
     */
    private int timeOut = 2000;

    @Autowired
    private EventProvider eventProvider;

    @Autowired
    private ReportAnalyzer reportAnalyzer;

    @Autowired
    private ScriptExecutor scriptExecutor;

    @PostConstruct
    public void schedule() {
        while (true) {
            new Thread(this::tryNewEvent).start();
            try {
                Thread.sleep(period);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * 尝试新事件
     */
    private void tryNewEvent() {
        if (this.eventProvider.isExecuteNewEvent()) {
            if (triggerStart()) {//事件开始
                if (!this.reportAnalyzer.analyzer(eventHandler())) {//事件处理以及分析报告
                    scriptExecutor.runScript();
                } else {
                    log.info("服务回归测试,测试正常");
                }
            }
            this.eventProvider.executeEventEnd();//结束事件
        }
    }

    /**
     * 触发开始
     */
    private boolean triggerStart() {
        log.info("准备触发事件开始--->{}", this.uri);
        try (CloseableHttpClient httpClient = HttpClients.createDefault()) {
            HttpPost post = new HttpPost(this.uri);
            post.setConfig(RequestConfig.custom()
                    .setConnectTimeout(this.timeOut)
                    .setSocketTimeout(this.timeOut)
                    .setConnectionRequestTimeout(this.timeOut)
                    .build());
            post.setEntity(new StringEntity(generateReport(),"utf-8"));
            try (CloseableHttpResponse execute = httpClient.execute(post)) {
                int statusCode = execute.getStatusLine().getStatusCode();
                if (statusCode >= 200 && statusCode <= 299) {
                    log.info("触发事件开始成功--->{},状态码--->{}", this.uri, statusCode);
                    return true;
                } else {
                    log.info("触发事件开始失败--->{},状态码--->{}", this.uri, statusCode);
                    return false;
                }
            } catch (Exception e) {
                log.error("触发事件开始失败--->{}",this.uri, e);
                return false;
            }
        } catch (Exception e) {
            log.error("触发事件开始失败--->{}", this.uri, e);
            return false;
        }
    }

    /**
     * 事件处理,所占用时间duration=serviceFinishTime+收集日志;
     */
    private List<String> eventHandler() {
        long cur = System.currentTimeMillis();
        List<String> targetList = new ArrayList<>();
        try {
            Thread.sleep(this.serviceFinishTime);
        } catch (InterruptedException e) {
            log.error("", e);
        }
        while ((System.currentTimeMillis() - cur) < this.duration) {
            String line = this.eventProvider.readLine();
            if (line != null && line.matches("^.*\r*" + this.key + ".*\r*$")) {
                targetList.add(line);
            }
        }
        return targetList;
    }

    /**
     * 生成报告
     */
    private String generateReport() {
        this.key="REG"+System.currentTimeMillis();
        log.info("生成关键字--->{}",this.key);
        return "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>\n" +
                "<ns2:ECReports xmlns:ns2=\"urn:epcglobal:ale:xsd:1\" specName=\"RegressionTest\" date=\"2020-08-13T09:58:14\" ALEID=\"TJKCHT\"\n" +
                "               totalMilliseconds=\"0\">\n" +
                "    <reports>\n" +
                "        <report reportName=\"RegressionTest\">\n" +
                "            <group>\n" +
                "                <groupList>\n" +
                "                    <member>\n" +
                "                        <rawHex>"+this.key+"</rawHex>\n" +
                "                        <extension\n" +
                "                                discoverLocation=\"LRName[RegressionTest]:Class[RD30]:ID[RegressionTest]:IP[RegressionTest]:Ant[2]:Protocol[EPC]\"\n" +
                "                                discoverTimestamp=\"1597284105021\" sightingCount=\"374\"/>\n" +
                "                    </member>\n" +
                "                </groupList>\n" +
                "            </group>\n" +
                "        </report>\n" +
                "    </reports>\n" +
                "</ns2:ECReports>";
    }
}
